﻿namespace AB.ServiceDirectory.Dao
{
    using System.Data.SqlClient;
    using System.Linq;
    using Commons.DataFilters;
    using Entities;

    /// <summary>
    /// ProgramDao Class
    /// </summary>
    public class ProgramDao
    {
        private readonly ServicesDirectoryDataContext _context = DB.Context;

        /// <summary>
        /// Checks the name of the program.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public bool CheckProgramName(string name)
        {
            Program program = _context.Programs.FirstOrDefault(p => p.ProgramName.Equals(name));
            return program != null;
        }

        /// <summary>
        /// Gets the program by id.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public Program GetProgramById(int id)
        {
            Program program = _context.Programs.FirstOrDefault(p => p.ProgramId == id);
            return program;
        }

        /// <summary>
        /// Adds the program.
        /// </summary>
        /// <param name="newProgram">The new program.</param>
        /// <returns></returns>
        public bool AddProgram(Program newProgram)
        {
            try
            {
                _context.Programs.InsertOnSubmit(newProgram);
                _context.SubmitChanges();
                return true;
            }
            catch (SqlException ex)
            {
                Log.GetLog(this).Error(ex);
                return false;
            }
        }

        /// <summary>
        /// Edits the program.
        /// </summary>
        /// <param name="newProgram">The new program.</param>
        /// <returns></returns>
        public bool EditProgram(Program newProgram)
        {
            try
            {
                Program oldProgram = _context.Programs.FirstOrDefault(p => p.ProgramId == newProgram.ProgramId);

                if (oldProgram != null)
                {
                    oldProgram.ProgramName = newProgram.ProgramName;
                    oldProgram.Description = newProgram.Description;
                    oldProgram.IsActive = newProgram.IsActive;
                    if (newProgram.ContactId != null)
                    {
                        Contact contact = HungContactDao.SelectContactById(newProgram.ContactId.Value);
                        oldProgram.Contact = contact;
                    }
                    else
                    {
                        oldProgram.Contact = null;
                    }

                    _context.SubmitChanges();
                    return true;
                }

                return false;
            }
            catch (SqlException ex)
            {
                Log.GetLog(this).Error(ex);
                return false;
            }
        }

        /// <summary>
        /// Edits the status.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public Program EditStatus(int id)
        {
            Program oldProgram = _context.Programs.FirstOrDefault(p => p.ProgramId == id);
            if (oldProgram != null)
            {
                oldProgram.IsActive = false;
            }
            _context.SubmitChanges();
            return oldProgram;
        }

        /// <summary>
        /// Gets the list.
        /// </summary>
        /// <param name="filter">The filter.</param>
        /// <param name="sortType">Type of the sort.</param>
        /// <param name="startRowIndex">Start index of the row.</param>
        /// <param name="max">The max.</param>
        /// <returns></returns>
        public IQueryable<Program> GetList(ProgramFilter filter, string sortType, int startRowIndex, int max)
        {
            IQueryable<Program> query = from p in _context.Programs
                                        select p;

            // 1. Filter by condition
            if (filter != null)
            {
                query = GetListQuery(query, filter);
            }

            // 2. Sorting
            query = GetListSort(query, sortType);

            // 3. Limit the rows
            if (startRowIndex != -1)
            {
                query = query.Skip(startRowIndex).Take(max);
            }

            return query;
        }

        /// <summary>
        /// Gets the list query.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <param name="filter">The filter.</param>
        /// <returns>Filtered list</returns>
        private static IQueryable<Program> GetListQuery(IQueryable<Program> query, ProgramFilter filter)
        {
            if (!filter.IncludeInactive)
            {
                query = query.Where(p => p.IsActive);
            }

            if (filter.BeginningLetters != null)
            {
                query = query.Where(p => filter.BeginningLetters.Contains(p.ProgramName[0].ToString()));
            }

            return query;
        }

        /// <summary>
        /// Gets the list sort.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <param name="sortType">Type of the sort.</param>
        /// <returns>Sorted list</returns>
        private static IQueryable<Program> GetListSort(IQueryable<Program> query, string sortType)
        {
            bool sortDescending = false;
            if (!string.IsNullOrEmpty(sortType))
            {
                string[] values = sortType.Split(' ');
                sortType = values[0];

                if (values.Length > 1)
                {
                    sortDescending = true;
                }

                switch (sortType)
                {
                    case "ProgramName":
                        query = sortDescending
                                    ? query.OrderByDescending(g => g.ProgramName)
                                    : query.OrderBy(g => g.ProgramName);
                        break;

                    case "ContactName":
                        query = sortDescending
                                    ? query.OrderByDescending(g => g.Contact.FirstName).ThenBy(g => g.Contact.Surname)
                                    : query.OrderBy(g => g.Contact.FirstName).ThenBy(g => g.Contact.Surname);
                        break;

                    case "Description":
                        query = sortDescending
                                    ? query.OrderByDescending(g => g.Description)
                                    : query.OrderBy(g => g.Description);
                        break;

                    case "IsActive":
                        query = sortDescending
                                    ? query.OrderByDescending(g => g.IsActive)
                                    : query.OrderBy(g => g.IsActive);
                        break;
                    default:
                        query = sortDescending
                                    ? query.OrderByDescending(g => g.ProgramId)
                                    : query.OrderBy(g => g.ProgramId);
                        break;
                }
            }

            return query;
        }

        /// <summary>
        /// Gets the list count.
        /// </summary>
        /// <param name="filter">The filter.</param>
        /// <returns>Number of rows</returns>
        public int GetListCount(ProgramFilter filter)
        {
            IQueryable<Program> data = from program in _context.Programs
                                       select program;

            return GetListQuery(data, filter).Count();
        }
    }
}